From One Report, Many

Using Parameterized Reporting to Generate
Dozens, Hundreds, or Thousands of Reports
at the Same Time

David Keyes // R for the Rest of Us

About Me

Why Parameterized Reporting?

Making multiple reports is tedious

Making multiple reports is error-prone

Making multiple reports is often not feasible

Parameterized Reporting Changes Everything

Or Imagine Having to Make One Report for Each NHS Trust in England

# A tibble: 274 × 2
    org_code admissions
    <fct>         <dbl>
  1 RF4            5060
  2 R1H            6943
  3 AD913             0
  4 RYX               0
  5 RQM            3597
  6 RJ6            2202
  7 Y02696            0
  8 NX122             0
  9 RVR            3360
 10 RJ1            3181
 11 Y03082            0
 12 RQX            1684
 13 RY9               0
 14 RYJ            3270
 15 RJZ            4477
 16 RAX            1839
 17 RJ2            4967
 18 R1K            4659
 19 RP6              11
 20 RAT               0
 21 RAP            2564
 22 Y02973            0
 23 AF003             0
 24 AF002             0
 25 RAL            3872
 26 Y03047            0
 27 RJ7            3814
 28 F84747            0
 29 RAS            2126
 30 Y03094            0
 31 E84068            0
 32 RKE            1347
 33 RRV            2182
 34 Y02147            0
 35 Y03201            0
 36 NL7               0
 37 8J094             0
 38 RDD            2468
 39 RC1            2022
 40 M85813            0
 41 RQ3             920
 42 RJF            1870
 43 RGT            3318
 44 RFS            1996
 45 NQ108             0
 46 RDE            2597
 47 Y03571            0
 48 RTG            3745
 49 RY8               0
 50 NNJ               0
 51 RWH            3222
 52 NQ106             0
 53 RLT            1119
 54 NTPAL             0
 55 NEH06             0
 56 RR1            6006
 57 RY4               0
 58 RQQ             856
 59 RGQ            1998
 60 RGP            1242
 61 RNQ            2555
 62 C82038            0
 63 RY5              18
 64 NJS05             0
 65 RC9            2650
 66 C82009            0
 67 NLO11             0
 68 NLO09             0
 69 RQ8            2291
 70 RD8            1468
 71 Y02652            0
 72 RM1            2612
 73 RGN            2406
 74 RNS            3303
 75 NMH01             0
 76 NR3               0
 77 RX1            4076
 78 NLO10             0
 79 C82010            0
 80 NLO12             0
 81 Y02428            0
 82 RXK            3067
 83 RK5            2765
 84 RXW            2441
 85 R1D               0
 86 Y02615            0
 87 RJC            1806
 88 RAJ            2314
 89 Y02470            0
 90 Y02961            0
 91 RNA            2425
 92 RQW            1835
 93 RCX            2049
 94 RL4            2606
 95 RWD            3502
 96 RRK            2818
 97 RKB            4077
 98 RWE            3758
 99 RJE            4511
100 RBK            1936
101 ATQ02             0
102 RWG            2701
103 RGR            2063
104 RWP            3201
105 RLQ            1185
106 REM            2718
107 RCF            1078
108 RBS            1130
109 RFF            2143
110 RXL            2247
111 RMC            2242
112 RAE            3045
113 NNF09             0
114 RY2               0
115 RWY            2628
116 RW3            3890
117 RLN            2650
118 RJR            1541
119 RXP            3387
120 RNN               0
121 RP5            3315
122 RJN             958
123 RXR            3054
124 NNF28             0
125 RR7            1670
126 RCD             988
127 RWA            3329
128 RV9               0
129 RXN            1721
130 Y01231            0
131 RR8            5213
132 Y02875            0
133 RY1               0
134 REP             111
135 Y01069            0
136 RBT            1840
137 RXF            5047
138 RNL            2055
139 RVW            1650
140 RTV               0
141 NLO01             0
142 RJL            2565
143 RTF            3975
144 RW6            5328
145 RT2               0
146 AC008             0
147 RQ6            2344
148 RM3            2637
149 AXT02             0
150 RCU             726
151 RHQ            2861
152 RTR            1919
153 RE9            1228
154 RVY            1905
155 RBN            3497
156 RWJ            2699
157 RMP            1708
158 RTD            2116
159 RFR            1671
160 RM2            2478
161 RTX            2019
162 RWW            2632
163 RY7               0
164 RBL            2546
165 AJN               0
166 RRF            1972
167 RCB            3543
168 RTK            1982
169 Y02688            0
170 NQT10             0
171 RWX               0
172 Y04538            0
173 RXH            3561
174 NLW               0
175 RXQ            2891
176 Y00058            0
177 NLT02             0
178 RJ8               1
179 RN7            2514
180 RBD            1310
181 RVV            3336
182 RXC            2801
183 DD401             0
184 RDU            6054
185 R1J               0
186 RTE            3464
187 RN3            2065
188 RN5            2428
189 NDA57             0
190 R1F             744
191 RYY               0
192 NR5               0
193 RWF            3677
194 RPA            2263
195 RVJ            2324
196 RBZ            1117
197 L83087            0
198 RNU               0
199 RTH            3100
200 NLX02             0
201 RK9            3008
202 RD3            1692
203 RHU            2921
204 RPC              31
205 RHW            3063
206 REF            2489
207 RH8            1849
208 RA2            2017
209 RD1            2103
210 RNZ            1062
211 Y02666            0
212 RH5               0
213 RYF               0
214 NTP11             0
215 RW1               9
216 NTPAD             0
217 RTP            2264
218 RDR               0
219 RBA            1773
220 AAH               0
221 RDZ            1876
222 RA9            2530
223 RHM            3456
224 RA7            2918
225 RYR            3199
226 RA3            1007
227 NDA56             0
228 G82071            0
229 NDA55             0
230 NLX24             0
231 RA4            1404
232 NAX               0
233 R1A               0
234 Y02646            0
235 NTP08             0
236 Y02613            0
237 RDY               3
238 Y02662            0
239 Y02568            0
240 Y02585            0
241 RYW               0
242 NLO20             0
243 Y02987            0
244 Y02596            0
245 NLO02             0
246 Y02565            0
247 E84069            0
248 Y02692            0
249 Y03218            0
250 Y03007            0
251 C83023            0
252 NNF70             0
253 NNF94             0
254 NNF99             0
255 R0A            6874
256 Y02532            0
257 Y03645            0
258 Y02572            0
259 Y02533            0
260 NQT5F             0
261 NNF76             0
262 NNF18             0
263 NTV0B             0
264 Y02676            0
265 Y00751            0
266 Y02816            0
267 NDJ               0
268 Y03051            0
269 NQT5H             0
270 Y02584            0
271 NTV0W             0
272 NNFA7             0
273 RW4               0
274 AXG               0

Parameterized Reporting is the Solution

How Parameterized Reporting Works

Make a Report

---
title: "Total Admissions Over Time"
format: 
  html:
    embed-resources: true
    css: styles.css
execute: 
  echo: false
  warning: false
  message: false
editor_options: 
  chunk_output_type: console
---

```{r}
library(tidyverse)
library(NHSRdatasets)
library(scales)
```


This chart shows total admissions over time in all NHS trusts.

```{r}
ae_attendances %>% 
  summarize(total_admissions = sum(admissions),
            .by = period) %>% 
  ggplot(aes(x = period,
             y = total_admissions)) +
  geom_line(alpha = 0.9,
            color = "#005EB8") +
  geom_area(alpha = 0.5,
            fill = "#005EB8") +
  scale_y_continuous(labels = comma_format()) +
  theme_minimal(base_family = "Frutiger") +
  theme(plot.title = element_text(face = "bold"),
        plot.title.position = "plot",
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank())
```

Manually Render One Report

Make a Report for One Location

---
title: "Total Admissions Over Time"
format: 
  html:
    embed-resources: true
    css: styles.css
execute: 
  echo: false
  warning: false
  message: false
editor_options: 
  chunk_output_type: console
---

```{r}
library(tidyverse)
library(NHSRdatasets)
library(scales)
```

This chart shows total admissions over time at RF4.

```{r}
ae_attendances %>% 
  filter(org_code == "RF4") %>% 
  summarize(total_admissions = sum(admissions),
            .by = period) %>% 
  ggplot(aes(x = period,
             y = total_admissions)) +
  geom_line(alpha = 0.9,
            color = "#005EB8") +
  geom_area(alpha = 0.5,
            fill = "#005EB8") +
  scale_y_continuous(labels = comma_format()) +
  theme_minimal(base_family = "Frutiger") +
  theme(plot.title = element_text(face = "bold"),
        plot.title.position = "plot",
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank())
```

Add a Parameter to Our Report

---
title: "Total Admissions Over Time"
format: 
  html:
    embed-resources: true
    css: styles.css
execute: 
  echo: false
  warning: false
  message: false
editor_options: 
  chunk_output_type: console
params:
  location: "RF4"
---

```{r}
library(tidyverse)
library(NHSRdatasets)
library(scales)
```


This chart shows total admissions over time at `r params$location`.

```{r}
ae_attendances %>% 
  filter(org_code == params$location) %>% 
  summarize(total_admissions = sum(admissions),
            .by = period) %>% 
  ggplot(aes(x = period,
             y = total_admissions)) +
  geom_line(alpha = 0.9,
            color = "#005EB8") +
  geom_area(alpha = 0.5,
            fill = "#005EB8") +
  scale_y_continuous(labels = comma_format()) +
  theme_minimal(base_family = "Frutiger") +
  theme(plot.title = element_text(face = "bold"),
        plot.title.position = "plot",
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.title = element_blank(),
        axis.ticks = element_blank())
```

Manually Render the Report (Again)

Manually Render Multiple Reports

Semi-Manually Render Report with R Script File

library(quarto)

quarto_render(
  input = "report.qmd",
  output_file = "RF4.html",
  execute_params = list(location = "RF4")
)

Automatically Render Multiple Reports with R Script File

# Load packages
library(tidyverse)
library(NHSRdatasets)
library(quarto)

# Create a vector of all locations
locations <- ae_attendances %>%
  distinct(org_code) %>% 
  mutate(org_code = as.character(org_code)) %>% 
  pull(org_code) 

# Create a tibble with information on the:
# input R Markdown document
# output HTML file
# parameters needed to knit the document
reports <- tibble(
  input = "report.qmd",
  output_file = str_glue("{locations}.html"),
  execute_params = map(locations, ~list(location = .))
)

# Use the tibble to generate all of our reports
pwalk(reports, quarto_render)

Summary

  1. Create report
  2. Add parameter to report
  3. Create render.R script file
  4. Create vector of all locations
  5. Create tibble with information about all reports
  6. Use reports tibble to render all reports

Learn More

Chapter from R Without Statistics ➜

Don’t Do It By Hand, Use Parameterized Reporting

  • Less tedious

  • Less error-prone

  • Makes it possible to generate reports that would not otherwise be feasible

Questions?

Ask in the chat or by email: david@rfortherestofus.com